<?php
namespace app\api\model;

use app\lib\exception\MissEx;
use think\Db;
use app\api\validate\IdMPot;

/** 
* Document
*/
class Order extends Base {
    
    protected $oProducts;  // 订单商品列表
    protected $products ;  // 库存商品信息
    protected $uid ;

    protected $info ; // 订单信息（表头）
    protected $items ; // 订单商品信息（表体）
    protected $pass;   // 有无库存

    protected $autoWriteTimestamp = true;
    protected $hidden =['update_time','delete_time'];
 
    public function getSnapItemsAttr($value){
        if (empty($value)) return [];
        return json_decode($value,true);
    }

    public function getSnapAddressAttr($value){
        if (empty($value)) return [];
        return json_decode($value,true);
    }


    /**
     * 通过用户提交订单信息实例化对象
     *
     * @param array $oProducts 用户提交订单信息
     * @param string $uid 用户信息主键
     * @return \app\api\model\Order
     */
    public static function initByProducts($oProducts,$uid='') {
        $order = new Order();
        $order->oProducts = $oProducts;
        # 查询订单商品在数据库中的信息
        $order->products = $order->getPorductByOrder($oProducts);
        empty($uid)? null : $order->uid = $uid;
        return $order;
    }
    /**
     * 通过订单记录主键实例化对象（一般用于检测、修改订单状态）
     *
     * @param int $id 订单记录的主键
     * @return \app\api\model\Order
     */
    public static function initById($id){
        $oProducts = OrderProduct::where(['order_id'=>$id])->field('order_id,product_id,count as quantity')->select();
        $oProducts = collection($oProducts)->toArray();
        $order = Order::get(['id'=>$id]);
        $order->oProducts = $oProducts;
        # 查询订单商品在数据库中的信息
        $order->products = $order->getPorductByOrder($oProducts);
        return $order;
    }
    /**
     * 创建订单
     *
     * @return 
     */
    public function place(){  // TODO 创建订单逻辑最好抽象到service里面
        # 完善订单信息+商品状态检测（库存）
        $pass = $this->getOrderStat();
        // 如果未通过库存检测 返回客户端某件商品缺货，不创建订单
        if ($pass == false) return false;
        
        # 开始创建订单信息（保存订单快照）
        Db::startTrans();
        $userAddress = UserAddress::getByUserID($this->uid);
        $this->data($this->info);
        $this->order_no = unID();
        $this->user_id = $this->uid;
        $this->snap_address = json_encode($userAddress);
        $this->snap_items = json_encode($this->items);
        $this->save();
        $orderProduct = new OrderProduct();

        foreach ($this->oProducts as $v) {
            $temp['order_id'] = $this->id;
            $temp['product_id'] = $v['product_id'];
            $temp['count'] = $v['quantity'];
            $opData[] = $temp;
        }
        $res = $orderProduct->saveAll($opData);
        if ($res) {
            Db::commit();
            return true;
        }else{
            Db::rollback();
            return false;
        }
        // 成功 返回
    }

    /**
     * 通过订单商品查询库存信息
     *
     * @param array $oProducts
     * @return array
     */
    private function getPorductByOrder( $oProducts){
        $oPIds = array_column($oProducts,'product_id');
        $products = collection(Product::all($oPIds))->visible(['id','price','stock','name','main_img_url']);
        return $products->toArray();
    }

    /**
     * 订单商品信息状态检测
     *
     * @return array
     */
    private function getOrderStat(){
        $order_pass = true;
        $pStatus =[
            'total_price' => 0,
            'total_count' => 0,
        ];
        $items = [];
        $pMax = 0;
        foreach ($this->oProducts as $k => $v) {
            $res = fInArray($this->products,'id',$v['product_id']);
            if($res == false) throw new MissEx('订单商品不存在',30006);
            // 记录订单中商品的相信信息
            $item = [
                'id'  => $res['id'],
                'name'=>$res['name'],
                'price' => $res['price'],
                'quantity' => $v['quantity'],
                'sum_price' => $v['quantity'] * $res['price'],
                'main_img_url' => $res['main_img_url'],
                'pass' => true,
            ];
            if($res['stock']-$v['quantity'] < 0) $item['pass'] = false;
            $order_pass = $order_pass && $item['pass'];

            $pStatus['total_price'] += $item['sum_price'];
            $pStatus['total_count'] += $item['quantity'];
            if ($item['sum_price'] > $pMax) {
                $pStatus['snap_name'] = $item['name'];
                $pStatus['snap_img'] = $item['main_img_url'];
                $pMax = $item['sum_price'];
            }
            array_push($items,$item);
        }
        $this->items = $items;
        $this->info = $pStatus;
        $this->pass = $order_pass;
        return $order_pass;
    }
    /**
     * 获取订单的信息（库存检查之后）
     *
     * @return array
     */
    public function getOrderInfo(){
        $res = $this->info;
        $res['pass'] = $this->pass;
        $res['items'] = $this->items;
        return $res;
    }

    /**
     * 检测订单是否有库存
     *
     * @return boolean
     */
    public function checkInStock(){
        return $this->getOrderStat();
    }
    
    /**
     * 检测订单的所有者
     *
     * @param int $uid 用户主键
     * @return boolean
     */
    public function checkOwner($uid){
        if($this->user_id == $uid) return true;
        else                       return false;
    }
    /**
     * 检测订单状态
     *
     * @param array $stat 订单状态码
     * @return boolean
     */
    public function checkInStatus($stat){
        if(is_array($stat)){
            return in_array($this->status,$stat);
        }else{
            return $this->status == $stat;
        }
    }

    /**
     * 获取用户历史订单记录
     *
     * @param int $uid
     * @param integer $page
     * @param integer $size
     * @return array
     */
    public static function getListByUser($uid,$page=1,$size=10){
        $pageData = self::where('user_id','=',$uid)
            ->order('create_time DESC')
            ->field('user_id,snap_items,snap_address,prepay_id',true)
            ->paginate($size,true,['page'=>$page]);
        return $pageData->toArray();
    }

    /**
     * 根据ID获取一条记录
     *
     * @param int $id
     * @return array
     */
    public static function getDetail($id){
        if(empty($id)) return [];
        $detail = self::get($id);
        if(empty($detail)) return [];
        $detail->hidden(['prepay_id']);
        return $detail->toArray();
    }
  
}